#include "tcpserver.h".

#include <stdio.h>
#include "eventloop.h"
#include "tcpsocket.h"

TcpServer::TcpServer(int port, EventLoop *loop, ThreadPool *pool)
{
    struct sockaddr_in servaddr;
    m_fd = ::socket(AF_INET,SOCK_STREAM,0);
    if(m_fd == -1)
    {
        ::perror("socket error:");
        ::exit(1);
    }
    //一个端口释放后会等待两分钟之后才能再被使用，SO_REUSEADDR是让端口释放后立即就可以被再次使用。
    int reuse_addr = 1;
    if(::setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, &reuse_addr, sizeof(reuse_addr)) == -1)
    {
        ::exit(1);
    }
    ::bzero(&servaddr,sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    //inet_pton(AF_INET,ip,&servaddr.sin_addr);
    servaddr.sin_addr.s_addr = ::htonl(INADDR_ANY);//绑定所有网卡所有IP
    servaddr.sin_port = ::htons(port);
    if(::bind(m_fd,(struct sockaddr*)&servaddr,sizeof(servaddr)) == -1)
    {
        ::perror("bind error: ");
        ::exit(1);
    }

    m_port = port;
    m_evLoop = loop;
    m_tdPool = pool;
    m_evLoop->registerServerEvent(m_fd,this);
}

TcpServer::~TcpServer()
{
    ::close(m_fd);
}

bool TcpServer::listen(void)
{
    !(::listen(m_fd,LISTENQ));
}

void TcpServer::createNewConnectCallback(NewConnectCallback func)
{
    m_newConnectFunc = std::move(func);
}

void TcpServer::handleAccept()
{
    struct sockaddr_in cliaddr;
    socklen_t cliaddrlen = sizeof(cliaddr);
    int fd = ::accept(m_fd,(struct sockaddr*)&cliaddr,&cliaddrlen);
    if(fd == -1)
    {
        ::perror("accpet error:");
    }else
    {
        ::printf("accept a new client: %s:%d,fd=%d\n",::inet_ntoa(cliaddr.sin_addr),cliaddr.sin_port,fd);
        //添加一个客户描述符和事件
        TcpSocket *socket = new TcpSocket(fd, m_evLoop, m_tdPool);
        m_socketMap[fd] = socket;
        if(m_evLoop->registerSocketEvent(fd,socket))
        {
            m_newConnectFunc(socket);
        }
    }
}
